import { isServer } from './is'

/**
 * 判断是否 十六进制颜色值.
 * 输入形式可为 #fff000 #f00 #0000ff78
 *
 * @param   String  color   十六进制颜色值
 * @return  Boolean
 */
export const isHexColor = (color: string) => {
  const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/
  return reg.test(color)
}

/**
 * RGB 颜色值转换为十六进制颜色值
 *
 * @return  String    #ff00ff
 * @param color rgb或rgba
 */
export const rgbToHex = (color: string) => {
  const { r, g, b } = parseRgbColor(color)
  const hex = ((r << 16) | (g << 8) | b).toString(16)
  return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex
}

/**
 * 十六进制颜色值转换为RGB 颜色值
 * @param {string} hex 需要转换的颜色
 * @returns 转换后得到的RGB颜色值
 */
export const hexToRGB = (hex: string, opacity?: number) => {
  let sHex = hex.toLowerCase()
  if (isHexColor(hex)) {
    if (sHex.length === 4) {
      let sColorNew = '#'
      for (let i = 1; i < 4; i += 1) {
        sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1))
      }
      sHex = sColorNew
    }
    const sColorChange: number[] = []
    for (let i = 1; i < 7; i += 2) {
      sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2)))
    }
    return opacity
      ? 'RGBA(' + sColorChange.join(',') + ',' + opacity + ')'
      : 'RGB(' + sColorChange.join(',') + ')'
  }
  return sHex
}

/**
 * 是否为深色系
 * @param {string} color 只能传入HEX颜色
 * @returns {void boolean}
 */
export const colorIsDark = (color: string) => {
  if (!isHexColor(color)) return
  const [r, g, b] = hexToRGB(color)
    .replace(/(?:\(|\)|rgb|RGB)*/g, '')
    .split(',')
    .map((item) => Number(item))
  return r * 0.299 + g * 0.578 + b * 0.114 < 192
}

/**
 * 解析颜色字符串为 RGB 对象
 */
const parseColor = (color: string): { r: number; g: number; b: number; a: number } => {
  color = color.trim().toLowerCase()

  // HEX 格式: #RRGGBB 或 #RGB
  if (color.startsWith('#')) {
    return parseHexColor(color)
  }

  // RGB 或 RGBA 格式
  if (color.startsWith('rgb')) {
    return parseRgbColor(color)
  }

  throw new Error(`Unsupported color format: ${color}`)
}

/**
 * 解析 HEX 颜色
 */
const parseHexColor = (color: string): { r: number; g: number; b: number; a: number } => {
  let hex = color.substring(1)

  // 处理缩写格式 #RGB
  if (hex.length === 3) {
    hex = hex
      .split('')
      .map((char) => char + char)
      .join('')
  }

  // 处理 #RRGGBBAA 格式
  if (hex.length === 8) {
    return {
      r: parseInt(hex.substring(0, 2), 16),
      g: parseInt(hex.substring(2, 4), 16),
      b: parseInt(hex.substring(4, 6), 16),
      a: parseInt(hex.substring(6, 8), 16) / 255
    }
  }

  // 处理 #RRGGBB 格式
  if (hex.length === 6) {
    return {
      r: parseInt(hex.substring(0, 2), 16),
      g: parseInt(hex.substring(2, 4), 16),
      b: parseInt(hex.substring(4, 6), 16),
      a: 1
    }
  }

  throw new Error(`Invalid HEX color format: ${color}`)
}

/**
 * 解析 RGB 颜色
 */
const parseRgbColor = (color: string): { r: number; g: number; b: number; a: number } => {
  const match = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/i)

  if (!match) {
    throw new Error(`Invalid RGB color format: ${color}`)
  }

  return {
    r: parseInt(match[1]),
    g: parseInt(match[2]),
    b: parseInt(match[3]),
    a: match[4] ? parseFloat(match[4]) : 1
  }
}

/**
 * 根据原始格式格式化颜色
 */
const formatColor = (
  rgb: { r: number; g: number; b: number; a: number },
  originalColor: string
): string => {
  const { r, g, b, a } = rgb

  // 检测原始颜色格式
  originalColor = originalColor.trim().toLowerCase()

  if (originalColor.startsWith('#')) {
    // HEX 格式
    const hex = [r, g, b]
      .map((value) => {
        const hex = Math.round(value).toString(16)
        return hex.length === 1 ? '0' + hex : hex
      })
      .join('')

    // 如果是带透明度的 HEX 格式
    if (originalColor.length === 9 || (originalColor.length === 5 && a < 1)) {
      const alphaHex = Math.round(a * 255)
        .toString(16)
        .padStart(2, '0')
      return `#${hex}${alphaHex}`
    }

    return `#${hex}`
  }

  if (originalColor.startsWith('rgba')) {
    // RGBA 格式
    return `rgba(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)}, ${a})`
  }

  if (originalColor.startsWith('rgb')) {
    // RGB 格式
    return `rgb(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)})`
  }

  // 默认返回 HEX 格式
  const hex = [r, g, b]
    .map((value) => {
      const hex = Math.round(value).toString(16)
      return hex.length === 1 ? '0' + hex : hex
    })
    .join('')

  return `#${hex}`
}

/**
 * 根据指定百分比减淡颜色（支持 HEX、RGB、RGBA 格式）
 * @param {string} color 需要变化的颜色值（支持 #RRGGBB、#RGB、rgb()、rgba() 格式）
 * @param {number} amount 颜色变化的程度（百分比，0-100之间）
 * @returns {string} 处理后的颜色（保持原始格式）
 */
export const lighten = (color: string, amount: number): string => {
  // 验证参数
  if (amount < 0 || amount > 100) {
    throw new Error('Amount must be between 0 and 100')
  }

  // 解析颜色为 RGB 对象
  const rgb = parseColor(color)

  // 计算亮度增量
  const increment = Math.trunc((200 * amount) / 100)

  // 增加亮度
  const lightenedRgb = {
    r: Math.min(255, rgb.r + increment),
    g: Math.min(255, rgb.g + increment),
    b: Math.min(255, rgb.b + increment),
    a: rgb.a
  }

  // 根据原始颜色格式返回相应格式的结果
  return formatColor(lightenedRgb, color)
}

/**
 * 根据指定百分比加深HEX格式的颜色
 * @param {string} color 需要处理的颜色值
 * @param {number} amount 颜色变化的程度（百分比）
 * @returns {string} 处理后的颜色的HEX表示
 */
export const darken = (color: string, amount: number) => {
  // 验证参数
  if (amount < 0 || amount > 100) {
    throw new Error('Amount must be between 0 and 100')
  }
  // 解析颜色为 RGB 对象
  const rgb = parseColor(color)

  // 计算亮度减少
  const decrement = Math.trunc((200 * amount) / 100)

  // 减少亮度
  const lightenedRgb = {
    r: Math.max(0, rgb.r - decrement),
    g: Math.max(0, rgb.g - decrement),
    b: Math.max(0, rgb.b - decrement),
    a: rgb.a
  }

  // 根据原始颜色格式返回相应格式的结果
  return formatColor(lightenedRgb, color)
}

/**
 * 计算RGB颜色的相对亮度值
 * 根据W3C Web内容可访问性指南(WCAG)的标准公式计算
 * @param {number} r 红色分量值 (0-255)
 * @param {number} g 绿色分量值 (0-255)
 * @param {number} b 蓝色分量值 (0-255)
 * @returns {number} 相对亮度值 (0-1之间的小数)
 */
const luminanace = (r: number, g: number, b: number) => {
  const a = [r, g, b].map((v) => {
    v /= 255
    return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4)
  })
  return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722
}

/**
 * 计算两种RGB颜色之间的对比度比值
 * 根据W3C Web内容可访问性指南(WCAG)的标准公式计算
 * @param {string[]} rgb1 第一种RGB颜色数组（字符串格式，如：["255", "0", "0"]）
 * @param {number[]} rgb2 第二种RGB颜色数组（数字格式，如：[255, 0, 0]）
 * @returns {number} 对比度比值（大于等于1的数值）
 */
const contrast = (rgb1: string[], rgb2: number[]) => {
  return (
    (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) /
    (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05)
  )
}

/**
 * 根据背景色与文本颜色的对比度计算最佳文本颜色（黑色或白色）
 * 基于WCAG可访问性标准，自动选择在给定背景色上可读性更好的文本颜色
 * @param hexColor - 用户选择的背景颜色（十六进制格式，如："#FF0000"）
 * @returns {string} 最佳文本颜色（"#000000"黑色或"#FFFFFF"白色）
 */
export const calculateBestTextColor = (hexColor: string) => {
  const rgbColor = hexToRGB(hexColor.substring(1))
  const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0])

  return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF'
}

// 预设颜色
export const PREDEFINE_COLORS = [
  '#ff4500',
  '#ff8c00',
  '#ffd700',
  '#90ee90',
  '#00ced1',
  '#1e90ff',
  '#c71585',
  '#409EFF',
  '#909399',
  '#C0C4CC',
  '#b7390b',
  '#ff7800',
  '#fad400',
  '#5b8c5f',
  '#00babd',
  '#1f73c3',
  '#711f57'
]

/**
 * 混合两种颜色，根据权重计算混合后的颜色
 * 通过分别混合RGB三个通道来实现颜色插值
 * @param {string} color1 - 第一种颜色，6位十六进制颜色代码（以`#`开头，如："#FF0000"）
 * @param {string} color2 - 第二种颜色，6位十六进制颜色代码（以`#`开头，如："#0000FF"）
 * @param {number} [weight=0.5] - 第一种颜色在混合中的权重，范围0-1（0表示100%使用color2，1表示100%使用color1）
 * @returns {string} 混合后的颜色，6位十六进制颜色代码（以`#`开头）
 */
export const mix = (color1: string, color2: string, weight: number = 0.5): string => {
  let color = '#'
  for (let i = 0; i <= 2; i++) {
    const c1 = parseInt(color1.substring(1 + i * 2, 3 + i * 2), 16)
    const c2 = parseInt(color2.substring(1 + i * 2, 3 + i * 2), 16)
    const c = Math.round(c1 * weight + c2 * (1 - weight))
    color += c.toString(16).padStart(2, '0')
  }
  return color
}

/**
 * getCssColorVariable
 * @description 获取css变量的颜色值
 * @param colorVariable css变量名
 * @param opacity 透明度
 * @returns {string} 颜色值
 * @example getCssColorVariable('--el-color-primary', 0.5)
 * @example getCssColorVariable('--el-color-primary')
 * @example getCssColorVariable()
 */
export const getCssColorVariable = (
  colorVariable: string = '--el-color-primary',
  opacity?: number
) => {
  const colorValue = getComputedStyle(document.documentElement)
    .getPropertyValue(colorVariable)
    .trim()
  if (colorValue) {
    return opacity ? hexToRGB(colorValue, opacity) : colorValue
  }
  return ''
}

/**
 * setCssColorVariable
 * @description 设置CSS自定义属性（变量）的颜色值
 * @param colorVariable CSS颜色变量名（默认为'--el-color-primary'）
 * @param colorValue 要设置的颜色值（十六进制、RGB、RGBA或有效CSS颜色值）
 * @param targetElement 目标元素，默认为文档根元素（:root）
 * @returns {boolean} 设置是否成功
 * @example setCssColorVariable('--el-color-primary', '#409EFF') // 设置主色调
 * @example setCssColorVariable('--el-color-primary', '#409EFF', document.getElementById('my-element')) // 设置特定元素的变量
 * @example setCssColorVariable('--bg-color', 'rgba(255, 0, 0, 0.5)') // 设置带透明度的颜色
 */
export const setCssColorVariable = (
  colorVariable: string = '--el-color-primary',
  colorValue: string,
  targetElement: HTMLElement = document.documentElement
): boolean => {
  if (isServer) {
    return false
  }

  try {
    // 验证输入参数
    if (!colorVariable || !colorValue) {
      console.warn('CSS变量名和颜色值不能为空')
      return false
    }

    // 验证变量名格式（应以--开头）
    if (!colorVariable.startsWith('--')) {
      console.warn('CSS变量名应以"--"开头')
      return false
    }

    // 验证颜色值格式（简单的格式检查）
    if (!isValidColorValue(colorValue)) {
      console.warn('颜色值格式无效:', colorValue)
      return false
    }

    // 验证目标元素是否存在
    if (!targetElement || !('style' in targetElement)) {
      console.warn('目标元素无效')
      return false
    }

    targetElement.style.setProperty(colorVariable, colorValue)

    return true
  } catch (error) {
    console.error('设置CSS变量时发生错误:', error)
    return false
  }
}

/**
 * 验证颜色值格式的辅助函数
 * @param colorValue 颜色值
 * @returns {boolean} 是否有效的颜色值
 */
const isValidColorValue = (colorValue: string): boolean => {
  // 创建临时元素测试颜色值有效性
  const tempElement = document.createElement('div')
  tempElement.style.color = colorValue

  // 如果颜色值有效，style.color会被解析为非空值
  const isValid = tempElement.style.color !== ''

  // 清理临时元素
  tempElement.remove()

  return isValid
}

/**
 * 批量设置多个CSS颜色变量
 * @param variables 颜色变量对象（键值对）
 * @param targetElement 目标元素，默认为文档根元素
 * @returns {boolean} 设置是否全部成功
 * @example
 * setCssColorVariables({
 *   '--el-color-primary': '#409EFF',
 *   '--el-color-success': '#67C23A',
 *   '--el-color-warning': '#E6A23C'
 * })
 */
export const setCssColorVariables = (
  variables: Record<string, string>,
  targetElement: HTMLElement = document.documentElement
): boolean => {
  let allSuccess = true

  if (isServer) {
    allSuccess = false
  }

  Object.entries(variables).forEach(([variable, value]) => {
    const success = setCssColorVariable(variable, value, targetElement)
    if (!success) {
      allSuccess = false
    }
  })

  return allSuccess
}

/**
 * 移除CSS颜色变量
 * @param colorVariable CSS颜色变量名
 * @param targetElement 目标元素，默认为文档根元素
 * @returns {boolean} 移除是否成功
 */
export const removeCssColorVariable = (
  colorVariable: string,
  targetElement: HTMLElement = document.documentElement
): boolean => {
  try {
    if (isServer) {
      return false
    }

    if (!colorVariable) {
      console.warn('CSS变量名不能为空')
      return false
    }

    targetElement.style.removeProperty(colorVariable)

    return true
  } catch (error) {
    console.error('移除CSS变量时发生错误:', error)
    return false
  }
}
